package org.apache.zookeeper.server.paxos2;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class Configuration {

	public static String storagePath = "/mnt/paxos2/";

	public static int blockSize = 4096;
	public static long noOfStripes = 3;
	public static int writeQuorumSize = 2;
	public static long totalSize = 96L * 1024L * 1024L * 1024L;
	public static long extraSize = 6L * 1024L * 1024L * 1024L;
	public static int cacheSize = 10;

	public static int preferredWriteBatchSize = 10;
	public static int preferredReadBatchSize = 300;
	public static int batchWaitTime = 1000;

	public static int serverId = 0;

	public static long timeoutInterval = 20000;

	public static int clientOutStanding = 200;

	public static String[] servers = { "application1-lan0", "application2-lan0",
			"application3-lan0"};

	public static boolean debug = false;

	public static final int metaBufferSize = 1048576;

	public static int syncInterval = 1000;

	public static int snapshotInterval = 1000000;

	public static int[][] keyMapping = new int[][] { new int[] { 0, 1, -1 },
			new int[] { -1, 0, 1 }, new int[] { 0, -1, 1 } };

	/*
	 * public static int [][] keyMapping = new int[][]{ new int[]{0,1,2}, new
	 * int[]{0,1,2}, new int[]{0,1,2}};
	 */

	public static void initialize(String fileName) {
		try {
			Properties properties = new Properties();
			properties.load(new FileInputStream(fileName));

			String tmp = properties.getProperty("blockSize");
			if (tmp != null)
				blockSize = Integer.parseInt(tmp);
			System.out.println("blockSize=" + blockSize);

			tmp = properties.getProperty("noOfStripes");
			if (tmp != null)
				noOfStripes = Integer.parseInt(tmp);
			System.out.println("noOfStripes=" + noOfStripes);

			tmp = properties.getProperty("writeQuorumSize");
			if (tmp != null)
				writeQuorumSize = Integer.parseInt(tmp);
			System.out.println("writeQuorumSize=" + writeQuorumSize);

			tmp = properties.getProperty("preferredWriteBatchSize");
			if (tmp != null)
				preferredWriteBatchSize = Integer.parseInt(tmp);

			tmp = properties.getProperty("preferredReadBatchSize");
			if (tmp != null)
				preferredReadBatchSize = Integer.parseInt(tmp);

			tmp = properties.getProperty("batchWaitTime");
			if (tmp != null)
				batchWaitTime = Integer.parseInt(tmp);

			tmp = properties.getProperty("clientOutStanding");
			if (tmp != null)
				clientOutStanding = Integer.parseInt(tmp);

			tmp = properties.getProperty("debug");
			if (tmp != null)
				debug = Boolean.parseBoolean(tmp);

			tmp = properties.getProperty("syncInterval");
			if (tmp != null)
				syncInterval = Integer.parseInt(tmp);

			tmp = properties.getProperty("snapshotInterval");
			if (tmp != null)
				snapshotInterval = Integer.parseInt(tmp);

			if (writeQuorumSize == 2)
				keyMapping = new int[][] { new int[] { 0, 1, 0 },
						new int[] { 0, 0, 1 }, new int[] { 0, 0, 1 } };
			else if (writeQuorumSize == 3 && noOfStripes ==3)
				keyMapping = new int[][] { new int[] { 0, 1, 2 },
						new int[] { 0, 1, 2 }, new int[] { 0, 1, 2 } };
			else if (writeQuorumSize == 3 && noOfStripes == 5)
				keyMapping = new int[][]{ new int[]{0,1,2,-1,-1},
							  new int[]{-1,0,1,2,-1},
							  new int[]{-1,-1,0,1,2},
							  new int[]{0,-1,-1,1,2},
							  new int[]{0,1,-1,-1,2}};
			else if (writeQuorumSize == 5 && noOfStripes == 5)
                                keyMapping = new int[][]{ new int[]{0,1,2,3,4},
                                                          new int[]{0,1,2,3,4},
                                                          new int[]{0,1,2,3,4},
                                                          new int[]{0,1,2,3,4},
                                                          new int[]{0,1,2,3,4}};

		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static boolean readAvailable = true;
	
	public synchronized static boolean isReadAvailable(){
		return readAvailable;
	}
	
	public synchronized static void setReadAvailable(boolean available){
		readAvailable = available;
	}

	private static final int outstandingLimit = 512*1024*1024/Configuration.blockSize;
	
	public static int outstandingCount=0;

	private static final Object outstandingLock = new Object();


	public static void increaseOutstanding(){
	    //if(true) return;
	    //System.out.println("outstanding="+outstandingCount);
	    synchronized(outstandingLock){
	    	while(outstandingCount>=outstandingLimit){
		    System.out.println("outstandingCount="+outstandingCount);
		    try{
		    	outstandingLock.wait();
		    }
		    catch(InterruptedException e){}
		    System.out.println("outstandingCount="+outstandingCount);
	    	}
	    	outstandingCount++;
	    }
	}

	public static void decreaseOutstanding(){
	    //System.out.println("outstanding="+outstandingCount);
	    synchronized(outstandingLock){
	    	outstandingCount--;
	    	if(outstandingCount==outstandingLimit-1)
		    outstandingLock.notifyAll();
	    }
	}
	
	public static boolean rereplicate = false;

	public static boolean simulateCheapPaxos = false;

	private static boolean inRecovery = false;

	public static synchronized boolean isInRecovery(){
		return inRecovery;
	}

	public static synchronized void setInRecovery(boolean value){
		inRecovery = value;
	}

	private static boolean busy = false;

        public static synchronized boolean isBusy(){
                return busy;
        }

        public static synchronized void setBusy(boolean value){
                busy = value;
        }

}
